<?php

namespace App\Jobs\Message;

use App\Constants\MemberTaskConstant;
use App\Constants\MiniProgramConstant;
use App\Constants\SignConstant;
use App\Constants\SmsConstant;
use App\Constants\TemplateMessageConstant;
use App\Models\Member;
use App\Models\MemberTask;
use App\Models\TemplateMessage;
use App\Services\TemplateMessageService;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldBeUnique;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Arr;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;

class SendMessage implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    protected $memberId;

    protected $type;

    protected $extend;

    protected $smsExtend;

    protected $errMsg;

    public function __construct(int $memberId, string $type, array $extend = [])
    {
        $this->memberId = $memberId;
        $this->type = $type;
        $this->extend = $extend;
    }

    public function handle()
    {
        if (!in_array($this->type, array_keys(TemplateMessageConstant::MAP))) {
            Log::error('发送微信订阅消息失败:' . $this->type . ' 未定义');
            return;
        }

        $this->errMsg = '发送' . TemplateMessageConstant::MAP[$this->type] . '失败：';

        $member = Member::find($this->memberId);
        if (!$member) {
            Log::error($this->errMsg . '会员[ID:' . $this->memberId . ']不存在', [
                'member_id' => $this->memberId,
                'type'      => $this->type
            ]);
            return;
        }

        $info = TemplateMessage::where([
            'mini_type' => $member->mini_type,
            'type'      => $this->type
        ])->first();

        if (!$info) {
            Log::error($this->errMsg . '模板ID不存在', [
                'member_id' => $this->memberId,
                'type'      => $this->type,
                'mini_type' => $member->mini_type,
            ]);
            return;
        }

        if (!$info->status) {
            return;
        }

        $settings = getMiniSettings($member->mini_type, MiniProgramConstant::GROUP);
        $appId = $settings[MiniProgramConstant::APP_ID] ?? '';
        $secret = $settings[MiniProgramConstant::APP_SECRET] ?? '';

        if (!$appId || !$secret) {
            Log::error($this->errMsg . '小程序[' . $member->mini_type . ']配置信息不完整', [
                'member_id' => $this->memberId,
                'type'      => $this->type,
                'app_id'    => $appId,
                'secret'    => $secret
            ]);
            return;
        }

        try {
            $service = new TemplateMessageService([
                'app_id' => $appId,
                'secret' => $secret
            ]);

            $method = Str::camel($this->type);

            $data = array_merge([
                'touser'      => $member->open_id,
                'template_id' => $info->template_id,
            ], $this->{$method}($member));

            $service->send($data);
        } catch (\Throwable $e) {
            Log::error($this->errMsg . $e->getMessage(), $data ?? []);
            return;
        }

        if ($member->phone && $this->smsExtend) {
            SendSms::dispatch(
                $member->phone,
                Arr::get($this->smsExtend, 'slug'),
                $member->id,
                Arr::get($this->smsExtend, 'data', [])
            );
        }
    }

    /**
     * 签到提醒
     * @param Member $member
     * @return array
     */
    protected function signInNotice(Member $member): array
    {
        $integral = getMiniSettings($member->mini_type, SignConstant::GROUP, SignConstant::DAY_INTEGRAL);

        return [
            'page' => '/pages/my/integral/sign',
            'data' => [
                'thing1'  => '每日签到',
                'thing2'  => '签到可获得' . $integral . '个积分',
                'phrase6' => '你还未签到',
            ],
        ];
    }

    /**
     * 分享邀请提醒
     * @param Member $member
     * @return array
     */
    protected function shareInviteNotice(Member $member): array
    {
        $integral = MemberTask::where('mini_type', $member->mini_type)
            ->where('slug', MemberTaskConstant::SLUG_BY_INVITE_REGISTER)
            ->value('integral') ?: 0;

        return [
            'page' => '/pages/my/integral/index',
            'data' => [
                'thing1'  => '分享好友注册',
                'number3' => $integral,
                'thing5'  => '戳我前往小程序完成任务 >>',
            ],
        ];
    }

    /**
     * 积分兑换
     * @param Member $member
     * @return array
     */
    protected function integralExchangeNotice(Member $member): array
    {
        return [
            'page' => '/pages/my/integral/exchangeCenter',
            'data' => [
                'phrase2' => '可兑换',
                'thing4'  => '您有' . $member->integral . '积分可兑换,请前往兑换中心兑换',
            ],
        ];
    }

    /**
     * VIP开通
     * @param Member $member
     * @return array
     */
    protected function vipOpenNotice(Member $member): array
    {
        $this->smsExtend = [
            'slug' => SmsConstant::TPL_TYPE_VIP_OPEN,
            'data' => [
                'date' => $this->extend['open_vip_date'] ?? ''
            ]
        ];

        return [
            'page' => '/pages/my/my',
            'data' => [
                'thing7' => ['value' => 'VIP'],
                'time5'  => ['value' => $this->extend['open_vip_date'] ?? ''],
            ],
        ];
    }

    /**
     * VIP即将到期
     * @param Member $member
     * @return array
     */
    protected function vipDueNotice(Member $member): array
    {
        $endDate = date('Y-m-d H:i:s', $member->vip_end_time);
        $day = Carbon::parse($endDate)->diffInDays(now());

        $this->smsExtend = [
            'slug' => SmsConstant::TPL_TYPE_VIP_DUE,
            'data' => [
                'day' => $day,
            ],
        ];

        return [
            'page' => '/pages/my/my',
            'data' => [
                'time3'  => ['value' => $endDate],
                'thing4' => ['value' => '会员还有' . $day . '天到期，请及时续费']
            ],
        ];
    }

    /**
     * VIP到期
     * @param Member $member
     * @return array
     */
    protected function vipExpireNotice(Member $member): array
    {
        $this->smsExtend = [
            'slug' => SmsConstant::TPL_TYPE_VIP_EXPIRE,
            'data' => []
        ];


        return [
            'page' => '/pages/my/my',
            'data' => [
                'thing1' => ['value' => 'vip'],
                'date2'  => ['value' => date('Y-m-d H:i:s', $member->vip_end_time)],
                'thing4' => ['value' => '您的vip已到期']
            ],
        ];
    }
}
